﻿// News Framework
// (C) Tanzim Saqib. Oct 25, 2010.
// http://TanzimSaqib.com | http://newsfx.codeplex.com

namespace TanzimSaqib.NewsFramework
{
    using System.Windows;
    using System.Windows.Controls;
    using System.Linq;
    using System.Windows.Controls.Primitives;

    public static class Command
    {
        /// <summary>
        /// A property definition representing attached triggers and messages.
        /// </summary>
        public static readonly DependencyProperty AttachProperty =
            DependencyProperty.RegisterAttached(
                "Attach",
                typeof(string),
                typeof(Command),
                new PropertyMetadata(OnAttachChanged)
                );

        /// <summary>
        /// Sets the attached triggers and messages.
        /// </summary>
        /// <param name="d">The element to attach to.</param>
        /// <param name="attachText">The parsable attachment text.</param>
        public static void SetAttach(DependencyObject d, string attachText)
        {
            d.SetValue(AttachProperty, attachText);
        }

        /// <summary>
        /// Gets the attached triggers and messages.
        /// </summary>
        /// <param name="d">The element that was attached to.</param>
        /// <returns>The parsable attachment text.</returns>
        public static string GetAttach(DependencyObject d)
        {
            return d.GetValue(AttachProperty) as string;
        }

        private static void OnAttachChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (e.NewValue == e.OldValue)
                return;

            var text = e.NewValue as string;
            if (string.IsNullOrEmpty(text))
                return;

            var tokens = text.Split(',');

            foreach(var token in tokens)
            {
                var splitted = token.Split('=');
                var eventName = splitted.First();
                var commandText = splitted.Last();

                if (d is ButtonBase)
                {
                    var b = d as ButtonBase;

                    if (!Fx.IsDesignMode)
                    {
                        switch (eventName)
                        {
                            case "Click":
                                b.Click += (src, ea) => b.DataContext
                                    .GetType()
                                    .GetMethod(commandText)
                                    .Invoke(b.DataContext, new object[] { new CommandArgs(d, e, ea) });
                                break;

                            default:
                                break;
                        }
                    }
                }
                else if (d is Selector)
                {
                    var s = d as Selector;

                    if (!Fx.IsDesignMode)
                    {
                        switch (eventName)
                        {
                            case "SelectionChanged":
                                s.SelectionChanged += (src, ea) => s.DataContext
                                    .GetType()
                                    .GetMethod(commandText)
                                    .Invoke(s.DataContext, new object[] { new CommandArgs(d, e, ea) });
                                break;

                            default:
                                break;
                        }
                    }
                }
                else if (d is TextBox)
                {
                    var t = d as TextBox;

                    if (!Fx.IsDesignMode)
                    {
                        switch (eventName)
                        {
                            case "TextChanged":
                                t.TextChanged += (src, ea) => t.DataContext
                                    .GetType()
                                    .GetMethod(commandText)
                                    .Invoke(t.DataContext, new object[] { new CommandArgs(d, e, ea) });
                                break;

                            default:
                                break;
                        }
                    }
                }
                else if (d is FrameworkElement)
                {
                    var fe = d as FrameworkElement;

                    if (!Fx.IsDesignMode)
                    {
                        switch (eventName)
                        {
                            case "Loaded":
                                fe.Loaded += (src, ea) => fe.DataContext
                                    .GetType()
                                    .GetMethod(commandText)
                                    .Invoke(fe.DataContext, new object[] { new CommandArgs(d, e, ea) });
                                break;

                            case "LostFocus":
                                fe.LostFocus += (src, ea) => fe.DataContext
                                    .GetType()
                                    .GetMethod(commandText)
                                    .Invoke(fe.DataContext, new object[] { new CommandArgs(d, e, ea) });
                                break;

                            default:
                                break;
                        }
                    }
                }
            }
        }
    }
}
